package cn.example.demo.modules.sys.service;

import cn.example.demo.common.model.service.ServiceResult;
import cn.example.demo.common.model.tree.factory.DefaultTreeBuildFactory;
import cn.example.demo.common.tools.obj.reflect.EntityUtils;
import cn.example.demo.modules.sys.dict.DictNameConstant;
import cn.example.demo.modules.sys.mapper.SysDepartmentMapper;
import cn.example.demo.modules.sys.mapper.SysUserDeptMapper;
import cn.example.demo.modules.sys.model.dto.SysDeptDto;
import cn.example.demo.modules.sys.model.entity.SysDepartment;
import cn.example.demo.modules.sys.model.entity.SysUserDept;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.benmanes.caffeine.cache.Cache;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * </p>
 *
 * @author Lizuxian
 * @create 2021-04-30 0:28
 */
@Service
public class DeptServiceImpl implements DeptService {
    @Resource
    private SysDepartmentMapper departmentMapper;
    @Resource
    private SysUserDeptMapper userDeptMapper;
    @Resource(name = "dictCache")
    private Cache<String, Object> dictCache;

    @Override
    public ServiceResult insertDept(SysDeptDto deptDto) {
        SysDepartment department = EntityUtils.entityConvert(deptDto, new SysDepartment(), false);
        department.setIsDirectory(true);
        department.setIsNode(true);

        if (deptDto.getParentNode() == null || deptDto.getParentNode() < 0) {
            department.setParentNode(DefaultTreeBuildFactory.ROOT_NODE);
        } else {
            department.setParentNode(deptDto.getParentNode());
        }

        int row = departmentMapper.insert(department);
        if (row == 1) {
            // 数据权限：组织树
            ServiceResult result = queryOrgTreeWithFlatChild(true);
            if (HttpStatus.OK.value() == result.getStatus()) {
                // 刷新缓存
                dictCache.put(DictNameConstant.ORGANIZATION_TREE_LIST, result.getData());
            }

            return ServiceResult.isSuccess("部门创建成功!", department);
        }

        return ServiceResult.isInternalError("部门创建失败，未知错误！");
    }

    @Override
    public ServiceResult updateDept(SysDeptDto deptDto) {
        SysDepartment department = EntityUtils.entityConvert(deptDto, new SysDepartment(), true);

        if (deptDto.getParentNode() != null && deptDto.getParentNode() >= DefaultTreeBuildFactory.ROOT_NODE) {
            department.setParentNode(deptDto.getParentNode());
        } else {
            department.setParentNode(DefaultTreeBuildFactory.ROOT_NODE);
        }

        department.setNode(deptDto.getNode());

        int row = departmentMapper.updateById(department);
        if (row == 1) {
            // 数据权限：组织树
            ServiceResult result = queryOrgTreeWithFlatChild(true);
            if (HttpStatus.OK.value() == result.getStatus()) {
                // 刷新缓存
                dictCache.put(DictNameConstant.ORGANIZATION_TREE_LIST, result.getData());
            }

            return ServiceResult.isSuccess("部门更新成功!", department);
        }

        return ServiceResult.isInternalError("部门更新失败，未知错误！");
    }

    @Override
    public ServiceResult deleteDept(Integer deptId) {
        int row = departmentMapper.deleteById(deptId);
        if (row != 0) {
            // 级联删除子级
            LambdaQueryWrapper<SysDepartment> wrapper1 = Wrappers.lambdaQuery();
            wrapper1.in(SysDepartment::getParentNode, deptId);
            List<Integer> nodes = departmentMapper.selectList(wrapper1).stream().map(SysDepartment::getNode).collect(Collectors.toList());
            if (!nodes.isEmpty()) {
                departmentMapper.deleteBatchIds(nodes);
            }

            // 删除用户组织绑定关系
            nodes.add(deptId);  // 含本级
            LambdaQueryWrapper<SysUserDept> wrapper2 = new LambdaQueryWrapper<>();
            userDeptMapper.delete(wrapper2.in(SysUserDept::getDeptId, nodes));

            // 数据权限缓存数据：组织树
            ServiceResult result = queryOrgTreeWithFlatChild(true);
            if (HttpStatus.OK.value() == result.getStatus()) {
                // 刷新缓存
                dictCache.put(DictNameConstant.ORGANIZATION_TREE_LIST, result.getData());
            }

            return ServiceResult.isSuccess("部门删除成功，id: " + deptId, null);
        }

        return ServiceResult.isNotModified("部门删除失败");
    }

    @Override
    public ServiceResult queryAllDeptListTree() {
        LambdaQueryWrapper<SysDepartment> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(SysDepartment::getRank, SysDepartment::getNode);

        List<SysDepartment> departments = departmentMapper.selectList(wrapper);

        if (departments.isEmpty()) {
            return ServiceResult.isNotFound("没有组织机构数据！");
        }

        // 列表转树结构
        return ServiceResult.isSuccess(new DefaultTreeBuildFactory<SysDepartment>().doTreeBuild(departments));
    }

    @Override
    public ServiceResult queryOrgTreeWithFlatChild(boolean isReturnMap) {
        List<SysDepartment> departments = departmentMapper.selectList(null);

        if (departments.isEmpty()) {
            return ServiceResult.isNotFound("没有组织机构数据！");
        }

        // 列表转树结构，子级平铺
        List<SysDepartment> list = new DefaultTreeBuildFactory<SysDepartment>().flattenChildren(departments);

        // 是否只返回 Map
        if (isReturnMap) {
            Map<Integer, Set<Integer>> orgChildTrees = list.stream().collect(Collectors.toMap(SysDepartment::getNode,
                    v -> v.getChildren().stream().map(SysDepartment::getNode).collect(Collectors.toSet())));

            return ServiceResult.isSuccess(orgChildTrees);
        }

        return ServiceResult.isSuccess(list);
    }

    @Override
    public ServiceResult queryAllDeptList() {
        List<SysDepartment> l = departmentMapper.selectList(null);
        if (l.isEmpty()) {
            return ServiceResult.isNotFound("暂无部门列表！");
        }
        List<Map<String, Object>> l1 = new ArrayList<>();
        l.forEach(o -> {
            Map<String, Object> m = new HashMap<>();
            m.put("code", o.getNode());
            m.put("name", o.getDeptName());
            l1.add(m);

        });
        return ServiceResult.isSuccess(l1);
    }

    @Override
    public boolean isExistDept(Integer deptId) {
        return departmentMapper.selectById(deptId) == null ? false : true;
    }

    @Override
    public SysDepartment findDeptById(Integer id) {
        return departmentMapper.selectById(id);
    }
}
